package io.github.echarts.model.geometry;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 表示由多个路径片段组成的完整路径
 * 可以用于描述复杂的图形
 */
public class Path {
    
    /**
     * 路径片段列表
     */
    private final List<PathSegment> segments;
    
    /**
     * 创建一个空路径
     */
    public Path() {
        this.segments = new ArrayList<>();
    }
    
    /**
     * 创建一个包含指定路径片段的路径
     * 
     * @param segments 路径片段列表
     */
    public Path(List<PathSegment> segments) {
        this.segments = new ArrayList<>();
        if (segments != null) {
            this.segments.addAll(segments);
        }
    }
    
    /**
     * 获取路径片段列表（只读）
     * 
     * @return 路径片段列表
     */
    public List<PathSegment> getSegments() {
        return Collections.unmodifiableList(segments);
    }
    
    /**
     * 添加路径片段
     * 
     * @param segment 路径片段
     * @return 当前路径对象，便于链式调用
     */
    public Path add(PathSegment segment) {
        if (segment != null) {
            segments.add(segment);
        }
        return this;
    }
    
    /**
     * 移动到指定点
     * 
     * @param point 目标点
     * @return 当前路径对象，便于链式调用
     */
    public Path moveTo(Point point) {
        return add(new MoveTo(point));
    }
    
    /**
     * 移动到指定坐标
     * 
     * @param x X坐标
     * @param y Y坐标
     * @return 当前路径对象，便于链式调用
     */
    public Path moveTo(double x, double y) {
        return add(new MoveTo(x, y));
    }
    
    /**
     * 从当前点连线到指定点
     * 
     * @param point 目标点
     * @return 当前路径对象，便于链式调用
     */
    public Path lineTo(Point point) {
        return add(new LineTo(point));
    }
    
    /**
     * 从当前点连线到指定坐标
     * 
     * @param x X坐标
     * @param y Y坐标
     * @return 当前路径对象，便于链式调用
     */
    public Path lineTo(double x, double y) {
        return add(new LineTo(x, y));
    }
    
    /**
     * 从当前点绘制三次贝塞尔曲线到指定点
     * 
     * @param control1 第一个控制点
     * @param control2 第二个控制点
     * @param end 终点
     * @return 当前路径对象，便于链式调用
     */
    public Path curveTo(Point control1, Point control2, Point end) {
        return add(new CurveTo(control1, control2, end));
    }
    
    /**
     * 从当前点绘制三次贝塞尔曲线到指定坐标
     * 
     * @param c1x 第一个控制点X坐标
     * @param c1y 第一个控制点Y坐标
     * @param c2x 第二个控制点X坐标
     * @param c2y 第二个控制点Y坐标
     * @param x 终点X坐标
     * @param y 终点Y坐标
     * @return 当前路径对象，便于链式调用
     */
    public Path curveTo(double c1x, double c1y, double c2x, double c2y, double x, double y) {
        return add(new CurveTo(c1x, c1y, c2x, c2y, x, y));
    }
    
    /**
     * 从当前点绘制弧线到指定点
     * 
     * @param radiusX X轴半径
     * @param radiusY Y轴半径
     * @param xAxisRotation X轴旋转角度（弧度）
     * @param largeArcFlag 是否选择大弧
     * @param sweepFlag 是否顺时针方向绘制
     * @param end 终点
     * @return 当前路径对象，便于链式调用
     */
    public Path arcTo(double radiusX, double radiusY, double xAxisRotation,
                     boolean largeArcFlag, boolean sweepFlag, Point end) {
        return add(new ArcTo(radiusX, radiusY, xAxisRotation, largeArcFlag, sweepFlag, end));
    }
    
    /**
     * 从当前点绘制弧线到指定坐标
     * 
     * @param radiusX X轴半径
     * @param radiusY Y轴半径
     * @param xAxisRotation X轴旋转角度（弧度）
     * @param largeArcFlag 是否选择大弧
     * @param sweepFlag 是否顺时针方向绘制
     * @param x 终点X坐标
     * @param y 终点Y坐标
     * @return 当前路径对象，便于链式调用
     */
    public Path arcTo(double radiusX, double radiusY, double xAxisRotation,
                    boolean largeArcFlag, boolean sweepFlag, double x, double y) {
        return add(new ArcTo(radiusX, radiusY, xAxisRotation, largeArcFlag, sweepFlag, x, y));
    }
    
    /**
     * 闭合路径（连接到路径的起始点）
     * 
     * @return 当前路径对象，便于链式调用
     */
    public Path close() {
        return add(ClosePath.INSTANCE);
    }
    
    /**
     * 获取路径的SVG路径数据字符串
     * 
     * @return SVG路径数据字符串
     */
    public String toSvgPathData() {
        StringBuilder pathData = new StringBuilder();
        
        for (PathSegment segment : segments) {
            pathData.append(segment.toSvgPathData()).append(" ");
        }
        
        return pathData.toString().trim();
    }
    
    /**
     * 计算路径的边界矩形
     * 
     * @return 边界矩形，如果路径为空则返回null
     */
    public Rectangle getBounds() {
        if (segments.isEmpty()) {
            return null;
        }
        
        // 找到第一个MoveTo片段作为起点
        Point currentPoint = null;
        Point firstPoint = null;
        List<Rectangle> segmentBounds = new ArrayList<>();
        
        for (PathSegment segment : segments) {
            if (segment instanceof MoveTo) {
                MoveTo moveTo = (MoveTo) segment;
                currentPoint = moveTo.getPoint();
                if (firstPoint == null) {
                    firstPoint = currentPoint;
                }
            } else {
                Rectangle bounds = segment.getBounds(currentPoint);
                if (bounds != null) {
                    segmentBounds.add(bounds);
                }
                
                // 更新当前点
                if (segment instanceof LineTo) {
                    currentPoint = ((LineTo) segment).getPoint();
                } else if (segment instanceof CurveTo) {
                    currentPoint = ((CurveTo) segment).getEnd();
                } else if (segment instanceof ArcTo) {
                    currentPoint = ((ArcTo) segment).getEnd();
                } else if (segment instanceof ClosePath && firstPoint != null) {
                    currentPoint = firstPoint;
                }
            }
        }
        
        if (segmentBounds.isEmpty()) {
            // 如果只有MoveTo片段，返回一个零尺寸的矩形
            if (currentPoint != null) {
                return new Rectangle(currentPoint.getX(), currentPoint.getY(), 0, 0);
            }
            return null;
        }
        
        // 计算所有片段边界的并集
        Rectangle result = segmentBounds.get(0);
        for (int i = 1; i < segmentBounds.size(); i++) {
            result = result.union(segmentBounds.get(i));
        }
        
        return result;
    }
    
    /**
     * 检查路径是否为空
     * 
     * @return 如果路径没有片段，返回true，否则返回false
     */
    public boolean isEmpty() {
        return segments.isEmpty();
    }
    
    /**
     * 获取路径片段数量
     * 
     * @return 路径片段数量
     */
    public int size() {
        return segments.size();
    }
    
    /**
     * 清空路径
     * 
     * @return 当前路径对象，便于链式调用
     */
    public Path clear() {
        segments.clear();
        return this;
    }
    
    /**
     * 创建一个新的Path，表示当前路径偏移指定距离后的结果
     * 
     * @param deltaX X轴偏移量
     * @param deltaY Y轴偏移量
     * @return 偏移后的新路径
     */
    public Path offset(double deltaX, double deltaY) {
        Path result = new Path();
        
        for (PathSegment segment : segments) {
            if (segment instanceof MoveTo) {
                MoveTo moveTo = (MoveTo) segment;
                Point point = moveTo.getPoint();
                result.add(new MoveTo(point.getX() + deltaX, point.getY() + deltaY));
            } else if (segment instanceof LineTo) {
                LineTo lineTo = (LineTo) segment;
                Point point = lineTo.getPoint();
                result.add(new LineTo(point.getX() + deltaX, point.getY() + deltaY));
            } else if (segment instanceof CurveTo) {
                CurveTo curveTo = (CurveTo) segment;
                Point c1 = curveTo.getControl1();
                Point c2 = curveTo.getControl2();
                Point end = curveTo.getEnd();
                result.add(new CurveTo(
                    c1.getX() + deltaX, c1.getY() + deltaY,
                    c2.getX() + deltaX, c2.getY() + deltaY,
                    end.getX() + deltaX, end.getY() + deltaY
                ));
            } else if (segment instanceof ArcTo) {
                ArcTo arcTo = (ArcTo) segment;
                Point end = arcTo.getEnd();
                result.add(new ArcTo(
                    arcTo.getRadiusX(), arcTo.getRadiusY(),
                    arcTo.getXAxisRotation(),
                    arcTo.isLargeArcFlag(), arcTo.isSweepFlag(),
                    end.getX() + deltaX, end.getY() + deltaY
                ));
            } else if (segment instanceof ClosePath) {
                result.add(ClosePath.INSTANCE);
            }
        }
        
        return result;
    }
    
    /**
     * 创建一个矩形路径
     * 
     * @param rect 矩形
     * @return 表示矩形的路径
     */
    public static Path createRectangle(Rectangle rect) {
        Path path = new Path();
        path.moveTo(rect.getX(), rect.getY())
            .lineTo(rect.getRight(), rect.getY())
            .lineTo(rect.getRight(), rect.getTop())
            .lineTo(rect.getX(), rect.getTop())
            .close();
        return path;
    }
    
    /**
     * 创建一个矩形路径
     * 
     * @param x 矩形左下角X坐标
     * @param y 矩形左下角Y坐标
     * @param width 矩形宽度
     * @param height 矩形高度
     * @return 表示矩形的路径
     */
    public static Path createRectangle(double x, double y, double width, double height) {
        return createRectangle(new Rectangle(x, y, width, height));
    }
    
    /**
     * 创建一个圆形路径
     * 
     * @param circle 圆形
     * @return 表示圆形的路径
     */
    public static Path createCircle(Circle circle) {
        Point center = circle.getCenter();
        double radius = circle.getRadius();
        
        // 使用四个贝塞尔曲线近似一个圆
        // 贝塞尔曲线控制点的魔数0.552284749831
        double control = radius * 0.552284749831;
        
        Path path = new Path();
        path.moveTo(center.getX() + radius, center.getY())  // 右中点
            .curveTo(
                center.getX() + radius, center.getY() + control,  // 右中点向上的控制点
                center.getX() + control, center.getY() + radius,  // 上中点向右的控制点
                center.getX(), center.getY() + radius             // 上中点
            )
            .curveTo(
                center.getX() - control, center.getY() + radius,  // 上中点向左的控制点
                center.getX() - radius, center.getY() + control,  // 左中点向上的控制点
                center.getX() - radius, center.getY()             // 左中点
            )
            .curveTo(
                center.getX() - radius, center.getY() - control,  // 左中点向下的控制点
                center.getX() - control, center.getY() - radius,  // 下中点向左的控制点
                center.getX(), center.getY() - radius             // 下中点
            )
            .curveTo(
                center.getX() + control, center.getY() - radius,  // 下中点向右的控制点
                center.getX() + radius, center.getY() - control,  // 右中点向下的控制点
                center.getX() + radius, center.getY()             // 右中点（回到起点）
            )
            .close();
        
        return path;
    }
    
    /**
     * 创建一个圆形路径
     * 
     * @param centerX 圆心X坐标
     * @param centerY 圆心Y坐标
     * @param radius 半径
     * @return 表示圆形的路径
     */
    public static Path createCircle(double centerX, double centerY, double radius) {
        return createCircle(new Circle(centerX, centerY, radius));
    }
    
    /**
     * 创建一个椭圆路径
     * 
     * @param centerX 中心X坐标
     * @param centerY 中心Y坐标
     * @param radiusX X轴半径
     * @param radiusY Y轴半径
     * @return 表示椭圆的路径
     */
    public static Path createEllipse(double centerX, double centerY, double radiusX, double radiusY) {
        // 使用四个贝塞尔曲线近似一个椭圆
        // 贝塞尔曲线控制点的魔数0.552284749831
        double controlX = radiusX * 0.552284749831;
        double controlY = radiusY * 0.552284749831;
        
        Path path = new Path();
        path.moveTo(centerX + radiusX, centerY)  // 右中点
            .curveTo(
                centerX + radiusX, centerY + controlY,  // 右中点向上的控制点
                centerX + controlX, centerY + radiusY,  // 上中点向右的控制点
                centerX, centerY + radiusY               // 上中点
            )
            .curveTo(
                centerX - controlX, centerY + radiusY,  // 上中点向左的控制点
                centerX - radiusX, centerY + controlY,  // 左中点向上的控制点
                centerX - radiusX, centerY               // 左中点
            )
            .curveTo(
                centerX - radiusX, centerY - controlY,  // 左中点向下的控制点
                centerX - controlX, centerY - radiusY,  // 下中点向左的控制点
                centerX, centerY - radiusY               // 下中点
            )
            .curveTo(
                centerX + controlX, centerY - radiusY,  // 下中点向右的控制点
                centerX + radiusX, centerY - controlY,  // 右中点向下的控制点
                centerX + radiusX, centerY               // 右中点（回到起点）
            )
            .close();
        
        return path;
    }
    
    /**
     * 从SVG路径数据字符串解析路径
     * 
     * @param svgPathData SVG路径数据字符串
     * @return 解析后的路径对象
     * @throws IllegalArgumentException 如果路径数据格式不正确
     */
    public static Path fromSvgPathData(String svgPathData) {
        // 这个方法需要一个完整的SVG路径解析器，这里只是一个简单的占位实现
        // 实际实现需要处理所有SVG路径命令，包括相对坐标、隐式命令重复等
        throw new UnsupportedOperationException("SVG路径解析尚未实现");
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        
        Path path = (Path) o;
        return Objects.equals(segments, path.segments);
    }
    
    @Override
    public int hashCode() {
        return segments != null ? segments.hashCode() : 0;
    }
    
    @Override
    public String toString() {
        return "Path{segments=" + segments + '}';
    }
} 